package cn.demoncat.util.ftp;

import java.io.IOException;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import cn.demoncat.util.conn.Conn;
import cn.demoncat.util.exception.BizErrorRuntimeException;
import cn.demoncat.util.exception.IoRuntimeException;
import cn.demoncat.util.ftp.config.FtpProperties;
import cn.demoncat.util.ftp.constant.FtpMsg;
import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.lang.constant.CharsetConstant;
import cn.demoncat.util.lang.constant.StringConstant;
import cn.demoncat.util.lang.constant.StatusConstant.Common;

/**
 * FTP连接
 * 
 * @author 延晓磊
 *
 * @since 2019年11月6日
 */
public class FtpConn extends Conn{

	// FTP客户端
	private final FTPClient client;
	// FTP根目录
	private final String root;
	
	/**
	 * 创建FTP连接
	 * 
	 * @param url
	 * @param config
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年11月6日
	 */
	public FtpConn(String url, FtpProperties config) {
		super(url, config);
		// FTP根目录
		this.root = config.getRoot();
		// FTP服务地址
		String[] hp = StringUtils.split(url, StringConstant.COLON);
		// FTP客户端
		client = new FTPClient();
		try {
			// 设置编码：允许中文路径
			client.setCharset(CharsetConstant.UTF8_CHARSET);
			client.setControlEncoding(CharsetConstant.UTF8);
			// 设置模式：FTP会开启不同的端口来传输数据，但Linux上由于安全限制，会禁用某些端口而造成阻塞
			if (Common.YES.equals(config.getMode())) {
				client.enterLocalActiveMode();
			}else {
				client.enterRemotePassiveMode();
			}
			// 设置缓冲区
			client.setBufferSize(config.getBuff());
			// 连接
			client.connect(hp[0], Integer.parseInt(hp[1]));
			if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
				throw new IoRuntimeException(StringUtil.logFormat("连接FTP服务器失败：url = {}, reply = {}", url, client.getReplyString()));
	        }
			// 登录
			boolean login = client.login(config.getUsername(), config.getPassword());
			if (!login) {
				throw new IoRuntimeException(StringUtil.logFormat("登录FTP服务器失败：url = {}, username = {}, reply = {}", url, config.getUsername(), client.getReplyString()));
			}
			// 设置文件类型：连接后设置，默认FTP.ASCII_FILE_TYPE
			client.setFileType(FTP.BINARY_FILE_TYPE);
		} catch (Exception e) {
			// 关闭连接
			close();
			throw new BizErrorRuntimeException(FtpMsg.CONN_ERROR, e);
		}
	}

	/**
	 * 关闭连接
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年11月6日
	 */
	@Override
	public void close() {
		// 退出登录
        try {
			client.logout();
		} catch (IOException e) {
			// 无操作
		}
    	// 断开连接
        try {
            client.disconnect();
        } catch (IOException e) {
           // 无操作
        }
	}
 
	/**
	 * 是否关闭
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年11月6日
	 */
	@Override
	public boolean isClosed() {
		return !client.isAvailable();
	}
 
	/**
	 * 校验连接
	 * 
	 * @return
	 * @throws IOException
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年11月6日
	 */
	@Override
	protected boolean toValid() throws IOException {
		return client.isAvailable() && client.sendNoOp();
	}

	/**
	 * 激活连接
	 * 
	 * @throws Exception
	 *
	 * @author 延晓磊
	 *
	 * @since 2019年11月6日
	 */
	@Override
	public void activate() throws Exception {
		// 切换到根目录：所有文件路径都是基于FTP安装路径的相对路径
		client.changeWorkingDirectory(root);
	}
	
	/**
	 * FTP客户端
	 * 
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年11月6日
	 */
	public FTPClient getClient() {
		return client;
	}

	
}
